#include "chartwidget.h"
#include "services/project/projectservice.h"
#include "services/window/windowservice.h"
#include "eventreceiver.h"
#include <QHeaderView>
#include <QFrame>
#include <QDate>
using namespace dpfservice;
ChartWidget::ChartWidget(QWidget *parent) : QWidget(parent), barChartView(new QChartView(this)),commitChartView(new QChartView(this)),codeChartView(new QChartView(this)),tableWidget(new QTableWidget(this)),codeLabel(new QLabel("总代码量为：0",this)),m_iniFile(new QSettings("src/plugins/myClock/data.ini", QSettings::IniFormat))
{
    // 主布局
    auto mainLayout = new QHBoxLayout;
    // 左侧布局
    QFrame *leftWidget = new QFrame;
    leftWidget->setFrameStyle(QFrame::Box | QFrame::Raised);
    QVBoxLayout *leftLayout = new QVBoxLayout(leftWidget);
    codeLabel->setWordWrap(true);
    leftLayout->addWidget(codeLabel, 1);
    
    tableWidget->setRowCount(1);
    tableWidget->setColumnCount(3);
    // 设置表头
    QStringList headers;
    headers << "文件类型" << "文件数量" << "代码量";
    tableWidget->setHorizontalHeaderLabels(headers);
    // 填充数据
    tableWidget->setItem(0, 0, new QTableWidgetItem("--"));
    tableWidget->setItem(0, 1, new QTableWidgetItem("--"));
    tableWidget->setItem(0, 2, new QTableWidgetItem("--"));
    tableWidget->item(0, 0)->setTextAlignment(Qt::AlignCenter);
    tableWidget->item(0, 0)->setFlags(tableWidget->item(0, 0)->flags() & ~Qt::ItemIsEditable);
    tableWidget->item(0, 1)->setTextAlignment(Qt::AlignCenter);
    tableWidget->item(0, 1)->setFlags(tableWidget->item(0, 1)->flags() & ~Qt::ItemIsEditable);
    tableWidget->item(0, 2)->setTextAlignment(Qt::AlignCenter);
    tableWidget->item(0, 2)->setFlags(tableWidget->item(0, 2)->flags() & ~Qt::ItemIsEditable);
    // 自动调整列宽
    tableWidget->verticalHeader()->setVisible(false);
    tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    leftLayout->addWidget(tableWidget, 9);

    // 右侧布局
    QFrame *rightWidget = new QFrame;
    rightWidget->setFrameStyle(QFrame::Box | QFrame::Raised);
    QGridLayout *rightLayout = new QGridLayout(rightWidget);
    
    initBarChart();

    rightLayout->addWidget(commitChartView, 0, 0);
    rightLayout->addWidget(codeChartView, 0, 1);
    rightLayout->addWidget(barChartView, 2, 0,1,2);

    mainLayout->addWidget(leftWidget, 3);
    mainLayout->addWidget(rightWidget, 7);
    this->setLayout(mainLayout);
    connect(EventReceiverProxy::instance(), &EventReceiverProxy::tableUpdate, this, &ChartWidget::getData);
    connect(EventReceiverProxy::instance(), &EventReceiverProxy::tableUpdate, this, &ChartWidget::initcommitLineChart);
    connect(EventReceiverProxy::instance(), &EventReceiverProxy::tableUpdate, this, &ChartWidget::initCodeLineChart);
}

void ChartWidget::getData()
{
    auto windowService = dpfGetService(dpfservice::WindowService);
    auto projectService = dpfGetService(dpfservice::ProjectService);
    auto prjInfo = projectService->getActiveProjectInfo();
    QString workspaceFolder = prjInfo.workspaceFolder();
    auto kitName = prjInfo.kitName();
    
    if (!kitName.isNull())
    {
        // 文件类型数
        QMap<QString, int> fileCounts;
        // 代码量
        QMap<QString, int> lineCounts;
        // 总代码量
        int totalLines = 0;

        QProcess findProcess;
        findProcess.setWorkingDirectory(workspaceFolder);
        QString command = QString("find . -type f -not -path './.git*' | sed 's/.*\\.//' | sort | uniq -c");
        findProcess.start("bash", QStringList() << "-c" << command);
        findProcess.waitForFinished();
        QString findOutput = findProcess.readAllStandardOutput();

        // 文件类型统计
        QStringList fileTypeLines = findOutput.split("\n", Qt::SkipEmptyParts);
        foreach (const QString &line, fileTypeLines)
        {
            QStringList parts = line.simplified().split(" ");
            if (parts.size() == 2)
            {
                int count = parts[0].toInt();
                QString extension = parts[1];
                fileCounts[extension] = count;
            }
        }

        // 代码量统计
        for (auto it = fileCounts.begin(); it != fileCounts.end(); ++it)
        {
            QString extension = it.key();
            QProcess grepProcess;
            grepProcess.setWorkingDirectory(workspaceFolder);
            QString command = QString("find . -type f -name \"*.%1\" -exec grep -v \"^$\" {} + | wc -l")
                                  .arg(extension);
            grepProcess.start("bash", QStringList() << "-c" << command);
            grepProcess.waitForFinished();
            QString grepOutput = grepProcess.readAllStandardOutput();
            int lineCount = grepOutput.trimmed().toInt();

            lineCounts[extension] = lineCount;
            totalLines += lineCount;
        }

        tableWidget->setRowCount(fileCounts.size());
        // 文件类型及数量注入表格
        int fileIndex=0;
        for (auto it = fileCounts.begin(); it != fileCounts.end(); ++it,++fileIndex)
        {
            QString files = QString("%1").arg(it.value());
            tableWidget->setItem(fileIndex, 0, new QTableWidgetItem(it.key()));
            tableWidget->setItem(fileIndex, 1, new QTableWidgetItem(files));
            tableWidget->item(fileIndex, 0)->setTextAlignment(Qt::AlignCenter);
            tableWidget->item(fileIndex, 1)->setTextAlignment(Qt::AlignCenter);
            tableWidget->item(fileIndex, 0)->setFlags(tableWidget->item(fileIndex, 0)->flags() & ~Qt::ItemIsEditable);
            tableWidget->item(fileIndex, 1)->setFlags(tableWidget->item(fileIndex, 1)->flags() & ~Qt::ItemIsEditable);

        }

        // 代码量注入表格
        int codeIndex=0;
        for (auto it = lineCounts.begin(); it != lineCounts.end(); ++it,++codeIndex)
        {
            QString codes = QString("%1").arg(it.value());
            tableWidget->setItem(codeIndex, 2, new QTableWidgetItem(codes));
            tableWidget->item(codeIndex, 2)->setTextAlignment(Qt::AlignCenter);
            tableWidget->item(codeIndex, 2)->setFlags(tableWidget->item(codeIndex, 2)->flags() & ~Qt::ItemIsEditable);
            // windowService->notify(1, "Line counts", codes, {});
        }

        QString codeTip = QString("总代码量：%1").arg(totalLines);
        codeLabel->setText(codeTip);
    }
}

void ChartWidget::initBarChart(){
    QStringList usedDays = m_iniFile->value("user_base/dev_date").toStringList();
    QStringList usedTime = m_iniFile->value("user_base/dev_time").toStringList();

    QDate currentDate = QDate::currentDate();
    QStringList last7Days;
    QMap<QString, double> dateToTime;

    for (int i = 6; i >= 0; --i) {
        QDate date = currentDate.addDays(-i);
        last7Days.append(date.toString("yyyy-MM-dd"));
    }
    for (int i = 0; i < usedDays.size(); ++i) {
        QDate date = QDate::fromString(usedDays[i], "yyyyMMdd");
        if (date.isValid()) {
            QString formattedDate = date.toString("yyyy-MM-dd");
            dateToTime[formattedDate] = QString::number(usedTime[i].toDouble() / 3600.0, 'f', 2).toDouble();
        }
    }

    // 填充柱状图数据
    QBarSet *barSet = new QBarSet("近7日坚持时长");
    for (const QString &day : last7Days) {
        if (dateToTime.contains(day)) {
            *barSet << dateToTime[day]; // 有数据
        } else {
            *barSet << 0; // 无数据
        }
    }

   
    // 创建柱状图
    QBarSeries *series = new QBarSeries();
    series->append(barSet);
    series->setLabelsVisible(true);
    series->setLabelsPosition(QAbstractBarSeries::LabelsOutsideEnd);


    barSet->setLabelColor(Qt::black);
    QFont labelFont = barSet->labelFont();
    labelFont.setPointSize(8);
    barSet->setLabelFont(labelFont);

    QChart *chart = new QChart();
    chart->addSeries(series);
    chart->setTitle("近7日坚持时长 (小时)");
    chart->setAnimationOptions(QChart::SeriesAnimations);

    // 设置 X 轴
    QBarCategoryAxis *axisX = new QBarCategoryAxis();
    axisX->append(last7Days);
    axisX->setLabelsAngle(45); // 倾斜 45 度
    QFont labelsFont = axisX->labelsFont();
    labelsFont.setPointSize(8); // 缩小字体
    axisX->setLabelsFont(labelsFont);
    axisX->setLabelsVisible(true); // 强制所有标签可见
    chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);

    // 设置 Y 轴
    QValueAxis *axisY = new QValueAxis();
    axisY->setTitleText("时长 (小时)");
    // axisY->setLabelFormat("%.2f");
    chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisY);

    // 创建图表视图
    barChartView->setChart(chart);
    barChartView->setRenderHint(QPainter::Antialiasing);
}

void ChartWidget::initcommitLineChart(){
    auto windowService = dpfGetService(dpfservice::WindowService);
    auto projectService = dpfGetService(dpfservice::ProjectService);
    auto prjInfo = projectService->getActiveProjectInfo();
    QString workspaceFolder = prjInfo.workspaceFolder();
    auto kitName = prjInfo.kitName();
    QProcess process;
    process.setWorkingDirectory(workspaceFolder);

    if (!kitName.isNull())
    {
        process.start("bash",QStringList() << "-c" <<"git config --global user.name");
        process.waitForFinished();
        QString userName = process.readAllStandardOutput().trimmed();
        if (userName.isEmpty()) {
            throw std::runtime_error("Failed to get the Git user name. Make sure it is configured.");
        }
        QStringList dates;
        QStringList commitCounts;
        QDate today = QDate::currentDate();
        for (int i = 0; i < 7; ++i) {
            QDate date = today.addDays(-i);
            QString dateStr = date.toString("yyyy-MM-dd");
            dates.append(dateStr);

            QString gitCommand = QString("git log --author='%1' --since='%2 00:00:00' --until='%2 23:59:59' --no-merges | grep -e 'commit [a-zA-Z0-9]*' | wc -l")
                                    .arg(userName, dateStr);

            process.start("bash", QStringList() << "-c" << gitCommand);
            process.waitForFinished();
            QString output = process.readAllStandardOutput().trimmed();
            int commitCount = output.toInt();
            commitCounts.append(QString::number(commitCount));
        }
        
     
        std::reverse(dates.begin(), dates.end());
        std::reverse(commitCounts.begin(), commitCounts.end());
  

        QLineSeries *lineSeries = new QLineSeries();
        for (int i = 0; i < dates.size(); ++i) {
            lineSeries->append(i, commitCounts[i].toInt());
        }
        lineSeries->setName("提交次数");
        lineSeries->setPointLabelsVisible(true);
        lineSeries->setPointLabelsColor(QColor(0,0,0));
        lineSeries->setPointLabelsFont(QFont("微软雅黑"));
        lineSeries->setPointLabelsFormat("@yPoint");
        lineSeries->setPointLabelsClipping(false);
        lineSeries->setPointsVisible(true);
        // 创建图表
        QChart *lineChart = new QChart();
        lineChart->addSeries(lineSeries);
        lineChart->setTitle("近7日提交次数统计");
        lineChart->legend()->setVisible(true);
        // 创建横坐标轴（日期）
        QCategoryAxis *axisX = new QCategoryAxis();
        for (int i = 0; i < dates.size(); ++i) {
            axisX->append(dates[i], i); // 将日期与索引对应
        }
        axisX->setTitleText("日期");
        QFont labelsFont = axisX->labelsFont();
        labelsFont.setPointSize(8); // 缩小字体
        axisX->setLabelsFont(labelsFont);
        axisX->setLabelsAngle(-45); // 倾斜显示日期标签
        QValueAxis *axisY = new QValueAxis();
        axisY->setTitleText("提交次数");
      
        axisY->setLabelFormat("%d");
        lineChart->addAxis(axisX, Qt::AlignBottom);
        lineChart->addAxis(axisY, Qt::AlignLeft);

        lineSeries->attachAxis(axisX);
        lineSeries->attachAxis(axisY);
        commitChartView ->setChart(lineChart);
        commitChartView->setRenderHint(QPainter::Antialiasing); // 抗锯齿
    }
}

void ChartWidget::initCodeLineChart(){
    auto windowService = dpfGetService(dpfservice::WindowService);
    auto projectService = dpfGetService(dpfservice::ProjectService);
    auto prjInfo = projectService->getActiveProjectInfo();
    QString workspaceFolder = prjInfo.workspaceFolder();
    auto kitName = prjInfo.kitName();
    QProcess process;
    process.setWorkingDirectory(workspaceFolder);

    if (!kitName.isNull())
    {
        process.start("bash",QStringList() << "-c" <<"git config --global user.name");
        process.waitForFinished();
        QString userName = process.readAllStandardOutput().trimmed();
        if (userName.isEmpty()) {
            throw std::runtime_error("Failed to get the Git user name. Make sure it is configured.");
        }
        QStringList dates;
        QStringList addCounts;
        QStringList removeCounts;
        QDate today = QDate::currentDate();
        for (int i = 0; i < 7; ++i) {
            QDate date = today.addDays(-i);
            QString dateStr = date.toString("yyyy-MM-dd");
            dates.append(dateStr);
            QString gitCommand = QString("git log --author='%1' --since='%2 00:00:00' --until='%2 23:59:59' --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }'").arg(userName, dateStr);
            process.start("bash", QStringList() << "-c" << gitCommand);
            process.waitForFinished();
            QString output = process.readAllStandardOutput().trimmed();
            // 默认值
            int addedLines = 0;
            int removedLines = 0;
            // 解析输出格式
            if (!output.isEmpty()) {
                QRegularExpression regex("added lines: (\\d*), removed lines: (\\d*), total lines: (\\d*)");
                QRegularExpressionMatch match = regex.match(output);
                if (match.hasMatch()) {
                    QString added = match.captured(1);
                    QString removed = match.captured(2);
                    addedLines = added.isEmpty() ? 0 : added.toInt();
                    removedLines = removed.isEmpty() ? 0 : removed.toInt();
                }
            }

            addCounts.append(QString::number(addedLines));
            removeCounts.append(QString::number(removedLines));
        }
        // 逆转三个列表
        std::reverse(dates.begin(), dates.end());
        std::reverse(addCounts.begin(), addCounts.end());
        std::reverse(removeCounts.begin(), removeCounts.end());
        // 创建两个折线系列
        QLineSeries *addSeries = new QLineSeries();
        QLineSeries *removeSeries =new QLineSeries();

        for (int i = 0; i < dates.size(); ++i) {
            // QDate date = QDate::fromString(dates[i], "yyyy-MM-dd");
            addSeries->append(i, addCounts[i].toInt());
            removeSeries->append(i, removeCounts[i].toInt());
        }
        addSeries->setName("新增代码量");
        removeSeries->setName("删除代码量");
        addSeries->setPointLabelsVisible(true);
        removeSeries->setPointLabelsVisible(true);
        addSeries->setPointLabelsColor(QColor(0,0,0));
        removeSeries->setPointLabelsColor(QColor(0,0,0));
        addSeries->setPointLabelsFont(QFont("微软雅黑"));
        removeSeries->setPointLabelsFont(QFont("微软雅黑"));
        addSeries->setPointLabelsFormat("@yPoint");
        removeSeries->setPointLabelsFormat("@yPoint");
        addSeries->setPointLabelsClipping(false);
        removeSeries->setPointLabelsClipping(true);
        addSeries->setPointsVisible(true);
        removeSeries->setPointsVisible(true);


        // 创建图表
        QChart *chart = new QChart();
        chart->addSeries(addSeries);
        chart->addSeries(removeSeries);
        chart->setTitle("近7日提交代码量统计");
        chart->legend()->setVisible(true);

        // 设置图表坐标轴
        QCategoryAxis *axisX = new QCategoryAxis();
        for (int i = 0; i < dates.size(); ++i) {
            axisX->append(dates[i], i);
        }
        
        axisX->setTitleText("日期");
        QFont labelsFont = axisX->labelsFont();
        labelsFont.setPointSize(8);
        axisX->setLabelsFont(labelsFont);
        axisX->setLabelsColor(QColor(0,0,0));
        axisX->setLabelsAngle(-45);
        

        chart->addAxis(axisX, Qt::AlignBottom);
        addSeries->attachAxis(axisX);
        removeSeries->attachAxis(axisX);

        QValueAxis *axisY = new QValueAxis();
        axisY->setTitleText("代码量");
        chart->addAxis(axisY, Qt::AlignLeft);
        addSeries->attachAxis(axisY);
        removeSeries->attachAxis(axisY);

        // 创建图表视图
        codeChartView ->setChart(chart);
        codeChartView->setRenderHint(QPainter::Antialiasing);
    }
}
